/**
 * 广寒宫
 * 网址:www.guanghangong.xyz
 */
package com.moon.admin.framework.mybatisplus.tenant;

import com.moon.admin.framework.MoonConstants;
import com.moon.admin.framework.mybatisplus.props.JdbcPoolProperties;
import com.moon.admin.framework.mybatisplus.props.JdbcProperties;
import com.moon.admin.framework.mybatisplus.props.MoonTenantProperties;
import com.moon.admin.framework.mybatisplus.tenant.domain.TenantDataSource;
import com.moon.admin.framework.secure.AuthUtils;
import com.moon.admin.framework.springmvc.config.SpringContextConfig;
import com.moon.admin.framework.util.JsonUtils;
import com.zaxxer.hikari.HikariDataSource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * 租户数据源切换拦截器
 * @author moon
 */
@Slf4j
@AllArgsConstructor
public class TenantDataSourceInterceptor implements HandlerInterceptor {

    private String applicationName;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        MoonTenantProperties moonTenantProperties = SpringContextConfig.getBean(MoonTenantProperties.class);
        //必须要开启datasource级别的租户才启用该拦截器
        if(MoonConstants.TenantTypeEnum.datasource.ordinal()!=moonTenantProperties.getType()){
            return true;
        }
        String tenantCode = AuthUtils.getTenantCode();
        Set<Object> keys = DynamicMultipleDataSource.dataSourcesMap.keySet();
        String dsName = tenantCode+applicationName;
        if(!keys.contains(dsName)){
            boolean success = setDynamicMultipleDataSource(tenantCode);
            if(success)DynamicMultipleDataSource.setDataSource(dsName);
        }else{
            DynamicMultipleDataSource.setDataSource(dsName);
        }
        return true;
    }

    private boolean setDynamicMultipleDataSource(String tenantCode){
        String sql = "select driverClass, url as jdbcUrl, username as userName, password,tenantCode,applicationName from dev_datasource t LEFT JOIN sys_tenant_datasource td on(t.id=td.datasourceId) where t.deleted = 0 and tenantCode=? and applicationName=?";
        List<TenantDataSource> tdsList = SpringContextConfig.getBean(JdbcTemplate.class).query(sql,new Object[]{tenantCode,applicationName},new BeanPropertyRowMapper<>(TenantDataSource.class));
        TenantDataSource dataSource = DataAccessUtils.uniqueResult(tdsList);
        if(dataSource==null)return false;
        JdbcPoolProperties jdbcPoolProperties = SpringContextConfig.getBean(JdbcPoolProperties.class);
        HikariDataSource hikariDataSource = DynamicMultipleDataSource.buildDataSource(jdbcPoolProperties);
        hikariDataSource.setJdbcUrl(dataSource.getJdbcUrl());
        hikariDataSource.setUsername(dataSource.getUserName());
        hikariDataSource.setPassword(dataSource.getPassword());
        DynamicMultipleDataSource.dataSourcesMap.put(dataSource.getTenantCode()+dataSource.getApplicationName(), hikariDataSource );
        DynamicMultipleDataSource dynamicDataSource = (DynamicMultipleDataSource) SpringContextConfig.getBean("dataSource");
        dynamicDataSource.setTargetDataSources(DynamicMultipleDataSource.dataSourcesMap);
        return true;
    }
}